/*Splay 平衡树
* 1.rotate(x) 将编号为x的点转到父节点的位置

* 2.splay(x,k) 将编号为x的点转到编号为k的点下面
    x会每次走两步，直到走到k下面
    为维护平衡树的效率
    每次splay时会把经过的路径反过来

* 3.用懒标记记录某点及其子树的翻转状态
    x的懒标记代表以x为根的子树对应的区间
    当翻转区间[l,r]时，将l-1转到根，r+1转到根的右儿子
                l-1
        [1~l-2]       r+1
                  [l~r] [r+2~n]
    改变r+1的左儿子的懒标记即可

* 本题:
    op I 插入节点
       A 每位员工+k
       S 每位员工-k
       F 查询排名为k
*/

#define DEBUG
#pragma GCC optimize("O1,O2,O3,Ofast")
#pragma GCC optimize("no-stack-protector,unroll-loops,fast-math,inline")
#pragma GCC target("avx,avx2,fma")
#pragma GCC target("sse,sse2,sse3,sse4,sse4.1,sse4.2,ssse3")

#include <iostream>
using namespace std;
#define L(u) (tree[tree[u].s[0]])
#define R(u) (tree[tree[u].s[1]])

const int N = 100010, INF = 0x3f3f3f3f;
int n, m;
struct node{
    int s[2], pa, v; //左右节点id 父节点id 当前点权值
    int size; //以当前节点为根的子树中节点的总数
    bool flag; //懒标记
    void init(int _v,int _pa){ //初始化 权值 父节点
        v=_v, pa=_pa;
        size=1;
    }
}tree[N];
int root,idx;
int delta; //平衡树中元素权值+delta才是真正数值
inline void pushup(int u)//维护子树大小,更新节点u的size
{  
    tree[u].size=L(u).size + R(u).size+1;
}

inline void pushdown(int u)//维护懒标记
{    
    if(tree[u].flag)
    {
        swap(tree[u].s[0], tree[u].s[1]);
        L(u).flag ^= 1;
        R(u).flag ^= 1;
        tree[u].flag=0;
    }
}

inline void rotate(int x)  //旋转 x上移一层
{
    int y=tree[x].pa, z=tree[y].pa; //父节点 祖父节点
    bool k=tree[y].s[1]==x; //x是否是父节点的子节点
    //交换x，y
    tree[z].s[tree[z].s[1]==y]=x; 
    tree[x].pa=z; 

    //将x的孩子节点接到y上
    tree[y].s[k]=tree[x].s[k^1], tree[tree[x].s[k^1]].pa=y;

    tree[x].s[k^1]=y, tree[y].pa=x;
    pushup(y), pushup(x);
}

inline void splay(int x,int k)//将x转到k下面
{ 
    while(tree[x].pa != k)
    {
        int y=tree[x].pa, z=tree[y].pa;
        if(z!=k)
        {
            if((tree[y].s[1]==x)^(tree[z].s[1]==y)) //不在一条直线上
                rotate(x);
            else
                rotate(y);
        }
        //此时x，x的父节点，x的祖父节点一定在一条直线上
        rotate(x);
    }
    if(!k) //x为根节点
        root=x;
}

inline void insert(int v) //加点(参数为权值)
{ 
    int u=root, pa=0; //
    while(u) //找到v的插入位置
        pa=u, u=tree[u].s[v>tree[u].v];
    u=++idx;
    tree[pa].s[v>tree[pa].v]=u;
    tree[u].init(v, pa);
    splay(u, 0); //将新插入节点旋转至根节点
}

inline int get_k(int k)    //查询中序遍历中排名为k的点
{
    int u=root;
    while(u)
    {
        pushdown(u);
        if(L(u).size>=k) //在左侧
            u=tree[u].s[0];
        else if(L(u).size+1==k) //当前节点就是待查找结点
            return u;
        else 
            k-=L(u).size+1, u=tree[u].s[1]; //在右侧，计算在右子树的排名
    }
    return -1;
}

int find(int val)
{
    int u=root, res=0;
    while(u)
    {
        if(val<=tree[u].v)
        {
            res=u;
            u=tree[u].s[0];
        }
        else u=tree[u].s[1];
    }
    return res;
}

signed main()
{
    #ifdef DEBUG
        freopen("./in.txt","r",stdin);
    #else
        ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    #endif

    cin >> n >> m;
    insert(-INF), insert(INF);

    int tot=0;
    for(int i=1; i<=n; i++)
    {
        char op;
        int k;
        cin >> op >> k;
        if(op=='I')
        {  //如果小于就不考虑了
            if(k>=m) k-=delta, insert(k), tot++;
        }
        else if(op=='A') delta+=k;
        else if(op=='S')
        {
            delta-=k;
            int l=1, r=find(m-delta);
            splay(l, 0); splay(r, l);
            tree[r].s[0]=0;
            pushup(r), pushup(l);
        }
        else {
            if(tree[root].size-2<k) cout << -1 << endl;
            else cout << tree[get_k(tree[root].size-k)].v+delta << endl;
        }
    }
    cout << tot-(tree[root].size-2) << endl;
    return 0;
}